<?php

/**
 * JingYao-backend
 *
 * @link     https://gitee.com/wang-zhihui-release/jingyao-backend
 * @apiDocument https://gitee.com/wang-zhihui-release/jingyao-backend/wikis/
 */

namespace App\Services;

use App\Enums\AdminCheckEnum;
use App\Enums\CheckStatusEnum;
use App\Enums\UserIdentityEnum;
use App\Events\CheckSuccess;
use App\Exceptions\ApiException;
use App\Format\CheckSuccessFormat;
use App\Format\HouseFormat;
use App\Models\House;
use App\Models\HouserScore;
use App\Models\HouserScoreResult;
use App\Models\HouseUserBind;
use App\Models\User;
use App\Models\UserProfile;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class HouseService
{
    public function createHouse(HouseFormat $houseFormat): House
    {
        $userId = $houseFormat->getHouserUserId();

        /** @var null|UserProfile $userProfile */
        $userProfile = UserProfile::query()->where('user_id', $userId)
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)
            ->exists();

        if (! $userProfile) {
            throw new ApiException('请先录入个人信息并审核通过才能录入房屋', 10);
        }

        $houseFormat->setCheckStatus(CheckStatusEnum::CHECK_ING);
        /** @var House $house */
        $data = $houseFormat->toArrayNotNull();
        if (isset($data['tenants'])) {
            unset($data['tenants']);
        }
        /* @var House $house */
        $house = House::query()->create($data);
        $this->setNeedCheckHouseNumber($userId);
        return $house;
    }

    public function updateHouse(HouseFormat $houseFormat): House
    {
        $id = $houseFormat->getId();
        if (empty($id)) {
            throw new ApiException('参数异常', 1);
        }
        /** @var null|House $house */
        $house = House::query()->find($houseFormat->getId());
        if (empty($house)) {
            throw new ApiException('要修改的房屋不存在', 1);
        }
        $houseFormat->setCheckStatus(CheckStatusEnum::CHECK_ING);
        $houseFormat->setId(null);
        $data = $houseFormat->toArrayNotNull();
        if (isset($data['tenants'])) {
            unset($data['tenants']);
        }
        $house->update($data);
        $this->setNeedCheckHouseNumber($houseFormat->getHouserUserId());
        return $house;
    }

    public function setHouseIdCardBind(int $houseId, string $idCardNum, string $name)
    {
        /** @var null|HouseUserBind $bind */
        $bind = HouseUserBind::query()->where('house_id', $houseId)
            ->where('id_card_number', $idCardNum)->first();
        if (empty($bind)) {
            return HouseUserBind::query()->create([
                'house_id' => $houseId,
                'id_card_number' => $idCardNum,
                'user_name' => $name,
            ]);
        }
        $bind->id_card_number = $idCardNum;
        $bind->save();
    }

    public function getHouseInfo(int $houseId)
    {
        $house = House::query()->find($houseId);
        if (! $house) {
            throw new ApiException('房屋不存在', 1);
        }
        $house = $house->toArray();
        $houser = UserProfile::query()->select('name', 'address')->where('user_id', $house['houser_user_id'])
            ->first();
        if (! $houser) {
            throw new ApiException('查无房东信息', 1);
        }
        $house['houser_name'] = $houser->name;
        $house['houser_address'] = $houser->address;
        $house['tenants'] = $this->getTenants($houseId);
        return $house;
    }

    public function getMyHouses(int $userId)
    {
        $houses = House::query()->with('tenants')->where('houser_user_id', $userId)->get()->toArray();
        if (empty($houses)) {
            return [];
        }
        return $houses;
    }

    public function getMyFinalScore(int $userId)
    {
        /** @var null|HouserScoreResult $scoreResult */
        $scoreResult = HouserScoreResult::query()->find($userId);
        if (empty($scoreResult)) {
            return [
                'houser_score' => 0,
            ];
        }
        return [
            'houser_score' => $scoreResult->houser_score,
        ];
    }

    // 审核房子 其实就是审核房东
    // 房子通过 房子的户主 (houser_user_id) 也就是房东了
    public function checkHouse(int $id, int $checkStatus, string $checkMessage)
    {
        /** @var null|House $house */
        $house = House::query()->find($id);
        if (empty($house)) {
            throw new ApiException('房屋不存在', 1);
        }
        $house->check_status = $checkStatus;
        $house->check_message = $checkMessage;
        $house->save();
        $houserUserId = $house->houser_user_id;
        // 有一套房子被通过就是房东身份
        if ($checkStatus == CheckStatusEnum::CHECK_ADOPT) {
            UserProfile::query()->where('user_id', $houserUserId)->update([
                'identity' => UserIdentityEnum::HOUSER,
            ]);
            User::query()->where('id', $houserUserId)->update([
                'identity' => UserIdentityEnum::HOUSER,
            ]);
        }
        $this->setNeedCheckHouseNumber($houserUserId);
        event(new CheckSuccess(new CheckSuccessFormat([
            'check_status' => $checkStatus,
            'check_type' => AdminCheckEnum::CHECK_HOUSE,
            'user_id' => $houserUserId,
        ])));
        return true;
    }

    public function checkHouserHouse(int $houserUserId, int $checkStatus)
    {
        $updateStatus = [
            'check_status' => $checkStatus,
        ];
        House::query()->where('houser_user_id', $houserUserId)->update($updateStatus);
        if ($checkStatus == CheckStatusEnum::CHECK_ADOPT) {
            UserProfile::query()->where('user_id', $houserUserId)->update([
                'identity' => UserIdentityEnum::HOUSER,
            ]);
            User::query()->where('id', $houserUserId)->update([
                'identity' => UserIdentityEnum::HOUSER,
            ]);
        }
    }

    public function deleteHouse(int $houseId)
    {
        DB::beginTransaction();
        try {
            // 删除房屋
            $house = House::query()->find($houseId);
            if (empty($house)) {
                throw new ApiException(sprintf('房屋【%s】不存在', $houseId), 1);
            }
            $house->delete();
            // 删除租客关联关系
            HouseUserBind::query()->where('house_id', $houseId)->delete();
            // 删除评分
            HouserScore::query()->where('house_id', $houseId)->delete();
            DB::commit();
        } catch (\Exception $e) {
            Log::error($e->getMessage());
            DB::rollBack();
        }
        return true;
    }

    public function getHouseTenants(int $houseId)
    {
        return HouseUserBind::query()->where('house_id', $houseId)->get();
    }

    public function deleteHouseTenants(int $houseId, array $idCardNums)
    {
        DB::beginTransaction();
        try {
            HouseUserBind::query()->where('house_id', $houseId)
                ->whereIn('id_card_number', $idCardNums)->delete();
            foreach ($idCardNums as $idCardNum) {
                /** @var null|UserProfile $profile */
                $profile = UserProfile::query()->select('user_id')
                    ->where('id_card_number', $idCardNum)
                    ->first();
                if (empty($profile)) {
                    continue;
                }
                // 租客 id
                $userId = $profile->user_id;
                HouserScore::query()->where('user_id', $userId)->delete();
            }
            DB::commit();
        } catch (\Exception $e) {
            Log::error($e->getMessage());
            DB::rollBack();
        }
        return true;
    }

    private function getTenants(int $houseId)
    {
        return HouseUserBind::query()
            ->select('id_card_number', 'user_name as name')
            ->where('house_id', $houseId)->get();
    }

    private function setNeedCheckHouseNumber(int $userId)
    {
        $number = House::query()->where('houser_user_id', $userId)
            ->where('check_status', CheckStatusEnum::CHECK_ING)
            ->count();
        $checkAdoptNumber = House::query()->where('houser_user_id', $userId)
            ->where('check_status', CheckStatusEnum::CHECK_ADOPT)
            ->count();
        UserProfile::query()->where('user_id', $userId)
            ->update([
                'need_check_house_number' => $number,
                'check_adopt_house_number' => $checkAdoptNumber,
            ]);
    }
}
